package com.zdp.middleware.hystrix.value.impl;

import com.alibaba.fastjson.JSON;
import com.netflix.hystrix.*;
import com.zdp.middleware.hystrix.annotation.DoHystrix;
import com.zdp.middleware.hystrix.value.IValveService;
import org.aspectj.lang.ProceedingJoinPoint;

import java.lang.reflect.Method;

/**
 * 继承 HystrixCommand<Object> 实现降级逻辑
 * @author ZhengDp
 * @Date 2023/5/27 11:44
 */
public class HystrixValueImpl extends HystrixCommand<Object> implements IValveService {

    private ProceedingJoinPoint jp;
    private Method method;
    private DoHystrix doHystrix;


    public HystrixValueImpl(){
        /*
        这里是不是动态设置比较好
        * 设置 HystrixGroup 的属性
        GroupKey : 该命令属于哪一个组
        CommandKey :  该命令的名称
        ThreadPoolKey : 该命令所属线程池的名称，同样配置的命令会共享同一线程池，若不配置，则默认使用GroupKey作为线程池名称
        CommandProperties : 该命令的一些设置，包括断路器的配置，隔离策略，降级设置，以及一些监控指标等
        ThreadPoolProperties : 关于线程池的配置，包括线程池大小，排队队列的大小等
        * */
        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("GovernGroup"))
                .andCommandKey(HystrixCommandKey.Factory.asKey("GovernKey"))
                .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("GovernThreadPool"))
                // 线程隔离
                .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
                        .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD))
                // 线程池大小10
                .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter().withCoreSize(10)));
    }

    /*
    * 正常的业务逻辑
    * */
    @Override
    protected Object run() throws Exception {
        try {
            return jp.proceed();
        } catch (Throwable e) {
            return null;
        }
    }

    /*
    * 降级逻辑
    * */
    @Override
    protected Object getFallback() {
        return JSON.parseObject(doHystrix.returnJson(),method.getReturnType());
    }

    @Override
    public Object access(ProceedingJoinPoint jp, Method method, DoHystrix doHystrix, Object[] args) throws Throwable {
        this.jp = jp;
        this.method = method;
        this.doHystrix = doHystrix;
        // 设置熔断超时时间
        Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("GrovernGropu"))
                .andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(doHystrix.timeoutValue()));
        // 调用 HystrixCommand 执行逻辑 ==> 同步执行
        return this.execute();
    }
}
